using System;
using System.IO;
using FireStarter.Base;
using FireStarter.CodeGeneration.Generator;
using FireStarter.CodeGeneration.Parser;
using FireStarterModeller.BO;

namespace FireStarter.CodeGeneration
{
    public class TemplateLoader
	{

        protected virtual string GetGeneratedTemplate(string fileContents, IModelElement modelElement)
        {
            ModelStrategyMapper modelStrategyMapper = new ModelStrategyMapper();
            modelStrategyMapper.SetStrategy(typeof (IModelElement), new ReflectionGenerationStrategy());

            StatementParser statementParser = new StatementParser();
            TemplateExpression templateExpression = statementParser.Parse(ref fileContents);
            return templateExpression.Generate(modelStrategyMapper, modelElement);
        }

        #region Project Structure Files

		public static string Csproj(CodeTemplateEnum codeTemplate)
		{
			const string fileName = "";
			string fileContents;
			if (!loadFromFile(fileName, out fileContents))
			{
			    fileContents = (codeTemplate == CodeTemplateEnum.CSharpVisualStudio2008)
                                   ? Templates.csprojTemplate2008v3_5 //Templates.csprojTemplate2008
			                       : Templates.csprojTemplate;
			}
			return fileContents;
		}

        public static string CsprojVWG(CodeTemplateEnum codeTemplate)
        {
            const string fileName = "";
            string fileContents;
            if (!loadFromFile(fileName, out fileContents))
            {
                fileContents = (codeTemplate == CodeTemplateEnum.CSharpVisualStudio2008)
                                   ? Templates.csprojTemplateVWG2008
                                   : Templates.csprojTemplateVWG;
            }
            return fileContents;
        }

        public static string Sln(CodeTemplateEnum codeTemplate)
        {
            const string fileName = "";
            string fileContents;
            if (!loadFromFile(fileName, out fileContents))
            {
                fileContents = (codeTemplate == CodeTemplateEnum.CSharpVisualStudio2008)
                                   ? Templates.Projects2008_sln
                                   : Templates.Projects_sln;
            }
            return fileContents;
        }

        //public static string Projects_sln(List<ProjectFileDetails> projects, string relativeToPath)
        //{
        //    string fileName = "";//@"D:\Habanero\FireStarter\FireStarter trunk\FireStarter.sln";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.Projects_sln;
        //    }
        //    string projectDefs = "";
        //    string projectConfigurations = "";
        //    foreach (ProjectFileDetails project in projects)
        //    {
        //        string relativePath = GenerateProjectFile.GetRelativePath(project.FullFileName, relativeToPath);
        //        projectDefs += "\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"" + project.Name +
        //                "\", \"" + relativePath + "\", \"" + project.ProjectGuid.ToString("B").ToUpper() +
        //                "\"\r\nEndProject";
        //        projectConfigurations += "\r\n\t\t" + project.ProjectGuid.ToString("B").ToUpper() + ".Debug|Any CPU.ActiveCfg = Debug|Any CPU";
        //        projectConfigurations += "\r\n\t\t" + project.ProjectGuid.ToString("B").ToUpper() + ".Debug|Any CPU.Build.0 = Debug|Any CPU";
        //        projectConfigurations += "\r\n\t\t" + project.ProjectGuid.ToString("B").ToUpper() + ".Release|Any CPU.ActiveCfg = Release|Any CPU";
        //        projectConfigurations += "\r\n\t\t" + project.ProjectGuid.ToString("B").ToUpper() + ".Release|Any CPU.Build.0 = Release|Any CPU";
        //    }
        //    projectDefs += "\r\n";
        //    projectConfigurations += "\r\n\t";
        //    fileContents = ReplaceSectionContents(fileContents, 
        //        "# Visual Studio 2005", "Global", projectDefs);
        //    fileContents = ReplaceSectionContents(fileContents,
        //        "GlobalSection(ProjectConfigurationPlatforms) = postSolution",
        //        "EndGlobalSection", projectConfigurations);
        //    //char[] chars = Encoding.ASCII.GetChars(new byte[] {239, 187, 191});
        //    //fileContents = chars[0] + chars[1] + chars[2] +
        //    //    fileContents;
        //    return fileContents;
        //}

		#endregion

        #region Required Files (All Projects)

        public string GetAssemblyInfo(string assemblyName)
        {
            const string fileName = "";
            string fileContents;
            if (!loadFromFile(fileName, out fileContents))
            {
                fileContents = Templates.AssemblyInfo_cs;
            }
            fileContents = SetAssemblySection(fileContents, "AssemblyTitle", assemblyName);
            fileContents = SetAssemblySection(fileContents, "AssemblyProduct", assemblyName);
            fileContents = SetAssemblySection(fileContents, "Guid", Guid.NewGuid().ToString());
            return fileContents;
        }

        #endregion

        //#region Required Files (UI Project)

        //public static string Resources_resx()
        //{
        //    string fileName = "";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.Resources_resx;
        //    }
        //    return fileContents;
        //}
		
        //public static string Resources_Designer_cs(string assemblyName)
        //{
        //    string fileName = "";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.Resources_Designer_cs;
        //    }
        //    fileContents = ReplaceSectionContents(fileContents,
        //        "namespace ", ".Properties", assemblyName);
        //    fileContents = ReplaceSectionContents(fileContents,
        //        "new global::System.Resources.ResourceManager(\"", 
        //        ".Properties.Resources\"", assemblyName);
        //    return fileContents;
        //}

        //public static string Settings_settings()
        //{
        //    string fileName = "";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.Settings_settings;
        //    }
        //    return fileContents;
        //}

        //public static string Settings_Designer_cs(string assemblyName)
        //{
        //    string fileName = "";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.Settings_Designer_cs;
        //    }
        //    fileContents = ReplaceSectionContents(fileContents,
        //        "namespace ", ".Properties", assemblyName);
        //    return fileContents;
        //}

        //#endregion

        //#region UI Program Files

        //public static string Program_cs(string projectName, string namespaceName, string projectVersion)
        //{
        //    string fileName = "";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.Program_cs;
        //    }
        //    if (String.IsNullOrEmpty(projectVersion))
        //    {
        //        projectVersion = "v1.0";
        //    }
        //    SetNamespaceTag(ref fileContents, namespaceName);
        //    fileContents = fileContents.Replace("<<PROJECT_NAME>>", projectName);
        //    fileContents = fileContents.Replace("<<PROJECT_VERSION>>", projectVersion);
        //    return fileContents;
        //}

        //public static string ProgramForm_cs(string projectName, string namespaceName, string uiNamespaceName)
        //{
        //    string fileName = "";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.ProgramForm_cs;
        //    }
        //    SetNamespaceTag(ref fileContents, namespaceName);
        //    SetNamespaceTag(ref fileContents, "UI_NAMESPACE", uiNamespaceName);
        //    SetCleanProjectNameTag(ref fileContents, projectName);
        //    return fileContents;
        //}

        //public static string ProgramForm_Designer_cs(string namespaceName)
        //{
        //    string fileName = "";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.ProgramForm_Designer_cs;
        //    }
        //    SetNamespaceTag(ref fileContents, namespaceName);
        //    return fileContents;
        //}

        //public static string FormController_cs(string projectName, string namespaceName, out string fileName)
        //{
        //    string templateFileName = "";
        //    string fileContents;
        //    if (!loadFromFile(templateFileName, out fileContents))
        //    {
        //        fileContents = Templates.FormController_cs;
        //    }
        //    SetNamespaceTag(ref fileContents, namespaceName);
        //    SetCleanProjectNameTag(ref fileContents, projectName);
        //    fileName = CleanupName(projectName) + "FormController.cs";
        //    return fileContents;
        //}

        //public static string App_config(DefDatabaseConfig defDatabaseConfig)
        //{
        //    string fileName = "";
        //    string fileContents;
        //    if (!loadFromFile(fileName, out fileContents))
        //    {
        //        fileContents = Templates.App_config;
        //    }
        //    string vendor = "";
        //    string server = "";
        //    string port = "";
        //    string database = "";
        //    string userName = "";
        //    string password = "";
        //    if (defDatabaseConfig != null)
        //    {
        //        DatabaseConfig databaseConfig;
        //        databaseConfig = defDatabaseConfig.DatabaseConfig;
        //        vendor = databaseConfig.Vendor;
        //        server = databaseConfig.Server;
        //        port = databaseConfig.Port;
        //        database = databaseConfig.Database;
        //        userName = databaseConfig.UserName;
        //        password = databaseConfig.Password;
        //    }
        //    fileContents = fileContents.Replace("<<VENDOR>>", vendor);
        //    fileContents = fileContents.Replace("<<SERVER>>", server);
        //    fileContents = fileContents.Replace("<<PORT>>", port);
        //    fileContents = fileContents.Replace("<<DATABASE>>", database);
        //    fileContents = fileContents.Replace("<<USERNAME>>", userName);
        //    fileContents = fileContents.Replace("<<PASSWORD>>", password);
        //    return fileContents;
        //}

        //#endregion

        #region Utility Methods

        public static bool loadFromFile(string fileName, out string fileContents)
        {
            bool loadFromFile = !string.IsNullOrEmpty(fileName) && File.Exists(fileName);
            if (loadFromFile)
            {
                StreamReader fileReader = new StreamReader(fileName);
                fileContents = fileReader.ReadToEnd();
                fileReader.Close();
            }
            else
            {
                fileContents = "";
            }
            return loadFromFile;
        }

        private static string SetAssemblySection(string fileContents, string sectionName, string sectionValue)
        {
            return ReplaceSectionContents(fileContents, "[assembly: " + sectionName + "(\"", "\")]", sectionValue);
        }

        protected static string ReplaceSectionContents(string source, string sectionPrefix, string sectionSuffix, string newContents)
        {
            int prefixPos = source.IndexOf(sectionPrefix);
            if (prefixPos < 0) return source;
            int contentStart = prefixPos + sectionPrefix.Length;
            int suffixPos = source.IndexOf(sectionSuffix, contentStart);
            if (suffixPos < 0) return source;
            return source.Substring(0, contentStart) + newContents + source.Substring(suffixPos);
        }

        public static void SetNamespaceTag(ref string fileContents, string projectName)
        {
            ReplaceTag(ref fileContents, "NAMESPACE", projectName);
        }

        protected static void SetBoReferenceTag(ref string fileContents, string projectName)
        {
            ReplaceTag(ref fileContents, "BOPROJECTNAME", projectName);
        }

        protected static void SetUIReferenceTag(ref string fileContents, string projectName)
        {
            ReplaceTag(ref fileContents, "UIPROJECTNAME", projectName);
        }

        protected static void SetProjectReferenceTag(ref string fileContents, string projectName)
        {
            ReplaceTag(ref fileContents, "PROJECTNAME", projectName);
        }

        protected static void SetClassNameTag(ref string fileContents, string className)
        {
            ReplaceTag(ref fileContents, "CLASSNAME", className);
        }

        private static void ReplaceTag(ref string fileContents, string tagName, string tagValue)
        {
            string referenceName = CleanupName(tagValue);
            fileContents = fileContents.Replace("<<" + tagName + ">>", referenceName);
        }

        //private static void SetCleanProjectNameTag(ref string fileContents, string projectName)
        //{
        //    fileContents = fileContents.Replace("<<CLEAN_PROJECT_NAME>>", CleanupName(projectName));
        //}

        private static string CleanupName(string name)
        {
            name = name.Replace(" ", "");
            name = name.Replace("-", "");
            //name = name.Replace("_", ""); 
            return name;
        }

        #endregion
	}
}